<template>
  <div class="beidou-grid-container">
    <!-- 北斗网格码控制面板 -->
    <div class="beidou-grid-control" :class="{ expanded: isPanelExpanded }">
      <!-- 控制图标 -->
      <div class="control-icon" @click="togglePanel" v-if="!isPanelExpanded" title="北斗网格码">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <!-- 北斗卫星轨道 -->
          <circle cx="12" cy="12" r="10"></circle>
          <circle cx="12" cy="12" r="6"></circle>
          <!-- 网格线 -->
          <line x1="12" y1="2" x2="12" y2="22"></line>
          <line x1="2" y1="12" x2="22" y2="12"></line>
          <line x1="4.93" y1="4.93" x2="19.07" y2="19.07"></line>
          <line x1="19.07" y1="4.93" x2="4.93" y2="19.07"></line>
          <!-- 北斗标志点 -->
          <circle cx="12" cy="12" r="2" fill="currentColor"></circle>
        </svg>
      </div>

      <!-- 控制面板 -->
      <div class="beidou-grid-panel" v-if="isPanelExpanded">
        <div class="panel-header">
          <h3>北斗网格码</h3>
          <div class="close-btn" @click="isPanelExpanded = false">
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M18 6L6 18M6 6l12 12"></path>
            </svg>
          </div>
        </div>

        <!-- 网格显示控制 -->
        <div class="control-section">
          <label class="checkbox-label">
            <input 
              type="checkbox" 
              v-model="gridVisible"
              @change="toggleGrid"
            >
            <span class="checkmark"></span>
            显示网格
          </label>
        </div>

        <!-- 网格级别控制 -->
        <div class="control-section" v-if="gridVisible">
          <label>网格级别: {{ gridLevel }}</label>
          <input 
            type="range" 
            v-model.number="gridLevel" 
            min="1" 
            max="20" 
            step="1" 
            class="level-slider"
            @change="updateGridLevel"
          >
          <div class="level-value">{{ gridLevel }}</div>
        </div>

        <!-- 编码显示控制 -->
        <div class="control-section" v-if="gridVisible">
          <label class="checkbox-label">
            <input 
              type="checkbox" 
              v-model="showCodes"
              @change="toggleCodes"
            >
            <span class="checkmark"></span>
            <span class="checkbox-text">显示编码</span>
          </label>
        </div>

        <!-- 当前位置编码 -->
        <div class="info-section" v-if="currentCode">
          <h4>当前位置编码</h4>
          <div class="code-display">{{ currentCode }}</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
import * as Cesium from 'cesium';

const props = defineProps({
  viewer: {
    type: Object,
    required: true
  }
});

// 状态管理
const isPanelExpanded = ref(false);
const gridVisible = ref(false);
const gridLevel = ref(10);
const showCodes = ref(true);
const currentCode = ref('');
const gridEntities = ref([]);
const codeEntities = ref([]);
let clickHandler = null;

// 切换面板展开/折叠状态
const togglePanel = () => {
  isPanelExpanded.value = !isPanelExpanded.value;
};

// 初始化北斗网格码
const initBeidouGrid = () => {
  if (!props.viewer) return;
  
  // 移除现有的网格和编码
  clearGrid();
  
  if (gridVisible.value) {
    drawGrid();
    if (showCodes.value) {
      drawCodes();
    }
  }
};

// 绘制网格
  const drawGrid = () => {
    if (!props.viewer) return;
    
    const scene = props.viewer.scene;
    const camera = props.viewer.camera;
    
    // 获取当前视口范围
    const extent = camera.computeViewRectangle();
    if (!extent) return false;
    
    // 计算网格大小（简化实现，实际应根据北斗网格码算法计算）
    const latRange = Cesium.Math.toDegrees(extent.north - extent.south);
    const lonRange = Cesium.Math.toDegrees(extent.east - extent.west);

    // 根据级别计算网格间隔，并保护 raw 值避免为 0 或非有限
    const rawBaseGridSize = Math.max(latRange, lonRange) / Math.pow(2, gridLevel.value / 2);
    const baseGridSize = (isFinite(rawBaseGridSize) && rawBaseGridSize > 0) ? rawBaseGridSize : 0;
    // 确保 gridSize 至少为 0.0125，避免 Cesium 绘制时出错或内部断言失败
    const gridSize = baseGridSize > 0 ? Math.max(baseGridSize, 0.0125) : 0.0125;

    // 如果计算结果仍然异常，则直接返回以避免无限循环或传入无效参数
    if (!isFinite(gridSize) || gridSize <= 0) return;
    
    // 绘制经纬度网格（简化实现）
    const startLat = Math.floor(Cesium.Math.toDegrees(extent.south) / gridSize) * gridSize;
    const startLon = Math.floor(Cesium.Math.toDegrees(extent.west) / gridSize) * gridSize;

    const endLat = Math.ceil(Cesium.Math.toDegrees(extent.north) / gridSize) * gridSize;
    const endLon = Math.ceil(Cesium.Math.toDegrees(extent.east) / gridSize) * gridSize;

    // 保护：计算步数并限制最大要绘制的网格数，避免在全局视图时生成过多实体或步长异常
    const latSteps = Math.floor((endLat - startLat) / gridSize);
    const lonSteps = Math.floor((endLon - startLon) / gridSize);
    const estimatedEntities = Math.max(0, latSteps) * Math.max(0, lonSteps);
    const MAX_ENTITIES = 3000;
    if (!isFinite(latSteps) || !isFinite(lonSteps) || estimatedEntities > MAX_ENTITIES) {
      // 视野过大或计算异常，跳过绘制以避免崩溃
      // console.warn('drawGrid: skipping draw, too many entities or invalid steps', {latSteps, lonSteps, estimatedEntities});
      return;
    }
    
    // 绘制纬线
    for (let lat = startLat; lat <= endLat; lat += gridSize) {
      // 确保起始点和结束点不同，避免绘制无效线条
      if (Math.abs(startLon - endLon) < 0.001) continue;
      
      const polyline = props.viewer.entities.add({
        polyline: {
          positions: Cesium.Cartesian3.fromDegreesArray([
            startLon, lat,
            endLon, lat
          ]),
          width: 3,
          material: new Cesium.PolylineGlowMaterialProperty({
            glowPower: 0.2,
            color: Cesium.Color.ORANGE
          })
        }
      });
      gridEntities.value.push(polyline);
    }
    
    // 绘制经线
    for (let lon = startLon; lon <= endLon; lon += gridSize) {
      // 确保起始点和结束点不同，避免绘制无效线条
      if (Math.abs(startLat - endLat) < 0.001) continue;
      
      const polyline = props.viewer.entities.add({
        polyline: {
          positions: Cesium.Cartesian3.fromDegreesArray([
            lon, startLat,
            lon, endLat
          ]),
          width: 3,
          material: new Cesium.PolylineGlowMaterialProperty({
            glowPower: 0.2,
            color: Cesium.Color.ORANGE
          })
        }
      });
      gridEntities.value.push(polyline);
    }
    return true;
  };

// 绘制编码
const drawCodes = () => {
  if (!props.viewer || !gridVisible.value) return false;
  
  const scene = props.viewer.scene;
  const camera = props.viewer.camera;
  
  // 获取当前视口范围
  const extent = camera.computeViewRectangle();
  if (!extent) return false;
  
  // 计算网格大小，并确保 gridSize 有效且不为 0（避免 Cesium 抛错）
  const latRange = Cesium.Math.toDegrees(extent.north - extent.south);
  const lonRange = Cesium.Math.toDegrees(extent.east - extent.west);
  const rawGridSize = Math.max(latRange, lonRange) / Math.pow(2, gridLevel.value / 2);
  // 强制最小网格大小，避免传入 0 或极小值导致 Cesium 内部断言失败
  const gridSize = (isFinite(rawGridSize) && rawGridSize > 0) ? Math.max(rawGridSize, 0.0125) : 0.0125;

  // 如果计算结果仍然异常，则直接返回
  if (!isFinite(gridSize) || gridSize <= 0) return false;

  const startLat = Math.floor(Cesium.Math.toDegrees(extent.south) / gridSize) * gridSize;
  const startLon = Math.floor(Cesium.Math.toDegrees(extent.west) / gridSize) * gridSize;

  const endLat = Math.ceil(Cesium.Math.toDegrees(extent.north) / gridSize) * gridSize;
  const endLon = Math.ceil(Cesium.Math.toDegrees(extent.east) / gridSize) * gridSize;
  
  // 每隔几个网格显示一个编码，避免过于密集
  const codeStep = Math.max(1, Math.floor(Math.pow(2, gridLevel.value / 4)));
  
  // 保护：估算标签总数并自适应增大 step，限制最大标签数
  const estLatCount = Math.max(0, Math.ceil((endLat - startLat) / (gridSize * codeStep)));
  const estLonCount = Math.max(0, Math.ceil((endLon - startLon) / (gridSize * codeStep)));
  const MAX_LABELS = 2000;
  let adaptiveCodeStep = codeStep;
  while (estLatCount * estLonCount > MAX_LABELS) {
    adaptiveCodeStep *= 2;
    // 重新计算估算数量
    const aLat = Math.max(0, Math.ceil((endLat - startLat) / (gridSize * adaptiveCodeStep)));
    const aLon = Math.max(0, Math.ceil((endLon - startLon) / (gridSize * adaptiveCodeStep)));
    if (aLat * aLon <= MAX_LABELS) break;
    // 如果 adaptiveCodeStep 过大仍未缩减，则当作不可绘制并返回
    if (adaptiveCodeStep > 1024) return;
  }

  for (let lat = startLat + gridSize / 2; lat < endLat; lat += gridSize * adaptiveCodeStep) {
    for (let lon = startLon + gridSize / 2; lon < endLon; lon += gridSize * adaptiveCodeStep) {
      // 生成模拟的北斗网格码（实际应使用真实算法）
      const code = generateMockBeidouCode(lon, lat, gridLevel.value);
      
      const label = props.viewer.entities.add({
        position: Cesium.Cartesian3.fromDegrees(lon, lat),
        label: {
          text: code,
          font: 'bold 12px sans-serif',
          fillColor: Cesium.Color.WHITE,
          outlineColor: Cesium.Color.BLACK,
          outlineWidth: 2,
          style: Cesium.LabelStyle.FILL_AND_OUTLINE,
          pixelOffset: new Cesium.Cartesian2(0, 0),
          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
          verticalOrigin: Cesium.VerticalOrigin.CENTER,
          showBackground: true,
          backgroundColor: Cesium.Color.BLACK.withAlpha(0.6),
          backgroundPadding: new Cesium.Cartesian2(6, 4)
        }
      });
      
      codeEntities.value.push(label);
    }
  }
  return true;
};

// 生成模拟的北斗网格码
const generateMockBeidouCode = (lon, lat, level) => {
  // 简化实现，生成模拟的北斗网格码
  const baseCode = `BD${level}`;
  const lonCode = Math.abs(Math.round(lon * 10000)).toString().padStart(8, '0');
  const latCode = Math.abs(Math.round(lat * 10000)).toString().padStart(8, '0');
  return `${baseCode}-${lonCode}-${latCode}`;
};

// 计算地理位置对应的北斗网格码
const getBeidouCode = (lon, lat, level) => {
  // 简化实现，实际应使用真实的北斗网格码算法
  return generateMockBeidouCode(lon, lat, level);
};

// 清除网格
const clearGrid = () => {
  // 移除网格实体
  gridEntities.value.forEach(entity => {
    props.viewer.entities.remove(entity);
  });
  gridEntities.value = [];
  
  // 移除编码实体
  codeEntities.value.forEach(entity => {
    props.viewer.entities.remove(entity);
  });
  codeEntities.value = [];
};

// 切换网格显示
const toggleGrid = () => {
  if (gridVisible.value) {
    // 立即尝试绘制；如果视图矩形尚未就绪，安排一次短延迟重试并在下一次 camera.moveEnd 时重试一次
    const gridOk = drawGrid();
    const codesOk = showCodes.value ? drawCodes() : true;
    addClickHandler();

    if (!gridOk || !codesOk) {
      // 短延迟重试（一次）
      const retryOnce = () => {
        try { initBeidouGrid(); } catch (e) {}
      };
      const timer = setTimeout(() => {
        retryOnce();
        clearTimeout(timer);
      }, 300);

      // 在下一次相机移动结束时再尝试一次，然后移除监听
      const oneTime = () => {
        try { initBeidouGrid(); } catch (e) {}
        try { props.viewer.camera.moveEnd.removeEventListener(oneTime); } catch (e) {}
      };
      try { props.viewer.camera.moveEnd.addEventListener(oneTime); } catch (e) {}
    }
  } else {
    clearGrid();
    removeClickHandler();
  }
};

// 更新网格级别
const updateGridLevel = () => {
  initBeidouGrid();
};

// 切换编码显示
const toggleCodes = () => {
  // 移除现有编码
  codeEntities.value.forEach(entity => {
    props.viewer.entities.remove(entity);
  });
  codeEntities.value = [];
  
  // 重新绘制编码
  if (showCodes.value && gridVisible.value) {
    drawCodes();
  }
};

// 添加点击事件处理
const addClickHandler = () => {
  if (!props.viewer) return;
  
  removeClickHandler();
  
  clickHandler = props.viewer.screenSpaceEventHandler.setInputAction((event) => {
    const pickedObject = props.viewer.scene.pick(event.position);
    if (Cesium.defined(pickedObject) && pickedObject.id) {
      // 点击到了实体
      const position = pickedObject.id.position;
      if (position) {
        const cartographic = Cesium.Cartographic.fromCartesian(position.getValue(Cesium.JulianDate.now()));
        const lon = Cesium.Math.toDegrees(cartographic.longitude);
        const lat = Cesium.Math.toDegrees(cartographic.latitude);
        currentCode.value = getBeidouCode(lon, lat, gridLevel.value);
      }
    } else {
      // 点击到了地图
      const ray = props.viewer.camera.getPickRay(event.position);
      const cartesian = props.viewer.scene.globe.pick(ray, props.viewer.scene);
      if (cartesian) {
        const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        const lon = Cesium.Math.toDegrees(cartographic.longitude);
        const lat = Cesium.Math.toDegrees(cartographic.latitude);
        currentCode.value = getBeidouCode(lon, lat, gridLevel.value);
      }
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
};

// 移除点击事件处理
const removeClickHandler = () => {
  if (props.viewer && clickHandler) {
    props.viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
    clickHandler = null;
  }
};

// 监听相机移动，更新网格
const handleCameraMove = () => {
  if (gridVisible.value) {
    // 延迟更新，避免频繁重绘
    setTimeout(() => {
      initBeidouGrid();
    }, 500);
  }
};

// 组件挂载时初始化
onMounted(() => {
  if (props.viewer) {
    // 添加相机移动事件监听
    props.viewer.camera.moveEnd.addEventListener(handleCameraMove);
  }
});

// 组件卸载时清理
onBeforeUnmount(() => {
  clearGrid();
  removeClickHandler();
  
  if (props.viewer) {
    // 移除相机移动事件监听
    props.viewer.camera.moveEnd.removeEventListener(handleCameraMove);
  }
});

// 监听网格级别变化
watch(gridLevel, () => {
  initBeidouGrid();
});
</script>

<style scoped>
/* 容器样式 */
.beidou-grid-container {
  position: absolute;
  top: 60px;
  right: 20px;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
}

/* 控制组件样式 */
.beidou-grid-control {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
  transition: all 0.3s ease;
}

/* 控制图标样式 */
.control-icon {
  width: 32px;
  height: 32px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 
    0 8px 32px rgba(102, 126, 234, 0.4),
    0 0 0 1px rgba(255, 255, 255, 0.1);
  transition: all 0.3s ease;
  color: white;
  z-index: 1001;
}

.control-icon:hover {
  transform: translateY(-2px);
  box-shadow: 
    0 12px 40px rgba(102, 126, 234, 0.6),
    0 0 0 1px rgba(255, 255, 255, 0.2);
}

/* 面板样式 */
.beidou-grid-panel {
  background: linear-gradient(135deg, rgba(15, 23, 42, 0.8) 0%, rgba(30, 41, 59, 0.8) 100%);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 10px;
  padding: 12px;
  min-width: 220px;
  opacity: 0;
  transform: translateY(20px) scale(0.95);
  pointer-events: none;
  transition: all 0.3s ease;
  box-shadow: 
    0 10px 25px rgba(0, 0, 0, 0.15),
    0 0 0 1px rgba(255, 255, 255, 0.08);
  z-index: 1000;
}

/* 面板展开状态 */
.beidou-grid-control.expanded .beidou-grid-panel {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: all;
}

/* 面板头部 */
.panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.15);
}

.panel-header h3 {
  margin: 0;
  color: white;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.5px;
}

/* 关闭按钮 */
.close-btn {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: rgba(255, 255, 255, 0.7);
  transition: all 0.2s ease;
}

.close-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  color: white;
}

/* 控制区域 */
.control-section {
  margin-bottom: 12px;
}

.control-section label {
  /* display: block; */
  margin-bottom: 8px;
  font-size: 11px;
  color: rgba(255, 255, 255, 0.9);
}

/* 复选框样式 */
.checkbox-label {
  display: flex;
  align-items: center;
  padding: 8px 10px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 6px;
  color: rgba(255, 255, 255, 0.95);
  cursor: pointer;
  transition: all 0.2s ease;
  font-size: 11px;
  font-weight: 500;
  width: 100%;
  box-sizing: border-box;
}

.checkbox-label:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.2);
}

.checkbox-label input {
  display: none;
}

.checkmark {
  width: 18px;
  height: 18px;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-radius: 4px;
  position: relative;
  transition: all 0.2s ease;
  margin-right: 8px;
  flex-shrink: 0;
}

.checkbox-text {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.checkbox-label input:checked + .checkmark {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-color: transparent;
}

.checkbox-label input:checked + .checkmark::after {
  content: '';
  position: absolute;
  left: 5px;
  top: 2px;
  width: 4px;
  height: 8px;
  border: solid white;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* 滑块样式 */
.level-slider {
  width: 100%;
  height: 4px;
  -webkit-appearance: none;
  appearance: none;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 2px;
  outline: none;
  transition: background 0.2s ease;
  margin: 8px 0;
}

.level-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 16px;
  height: 16px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 50%;
  cursor: pointer;
  transition: all 0.2s ease;
  box-shadow: 0 2px 6px rgba(102, 126, 234, 0.3);
  border: 2px solid rgba(255, 255, 255, 0.8);
}

.level-slider::-webkit-slider-thumb:hover {
  transform: scale(1.1);
  box-shadow: 0 3px 8px rgba(102, 126, 234, 0.5);
}

.level-slider::-moz-range-thumb {
  width: 16px;
  height: 16px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 50%;
  cursor: pointer;
  transition: all 0.2s ease;
  box-shadow: 0 2px 6px rgba(102, 126, 234, 0.3);
  border: 2px solid rgba(255, 255, 255, 0.8);
}

.level-slider::-moz-range-thumb:hover {
  transform: scale(1.1);
  box-shadow: 0 3px 8px rgba(102, 126, 234, 0.5);
}

/* 级别值显示 */
.level-value {
  text-align: center;
  font-size: 11px;
  color: rgba(255, 255, 255, 0.9);
  background: rgba(255, 255, 255, 0.1);
  padding: 2px 6px;
  border-radius: 3px;
  margin-top: 4px;
  width: 30px;
  margin-left: auto;
  margin-right: auto;
}

/* 信息区域 */
.info-section {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.info-section h4 {
  margin: 0 0 8px 0;
  font-size: 11px;
  color: rgba(255, 255, 255, 0.8);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

/* 编码显示 */
.code-display {
  background: rgba(0, 0, 0, 0.2);
  padding: 8px;
  border-radius: 4px;
  font-size: 10px;
  color: rgba(255, 255, 255, 0.9);
  word-break: break-all;
  font-family: monospace;
  width: 100%;
  box-sizing: border-box;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 确保SVG图标正确显示 */
.control-icon svg,
.close-btn svg {
  display: block;
  width: 18px;
  height: 18px;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .beidou-grid-panel {
    min-width: 180px;
    padding: 8px;
  }
  
  .control-icon {
    width: 28px;
    height: 28px;
  }
}
</style>
